home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / pascal / oop55.zip / BOUNDS.PAS next >
Pascal/Delphi Source File  |  1989-05-02  |  8KB  |  329 lines

  1.  
  2. { Copyright (c) 1989 by Borland International, Inc. }
  3.  
  4. unit Bounds;
  5. { Turbo Pascal 5.5 object-oriented example.
  6.   See BREAKOUT.PAS.
  7.   Contains the Paddle object type and the object types that
  8.   define the boundaries of the playfield.
  9.   This unit is part of the BREAKOUT.PAS example.
  10. }
  11.  
  12. interface
  13.  
  14. uses Screen, Bricks, Count, Crt;
  15.  
  16. type
  17.   ObstaclePtr = ^Obstacle;
  18.  
  19.   { An ObstacleList is a list of instances of objects derived from the
  20.   object Obstacle.  In order to use all these instances polymorphically,
  21.   All their virtual functions have to have corresponding virtual functions
  22.   in Obstacle, even if they are never used. }
  23.  
  24.   Obstacle = object(Location)
  25.     Width   : Integer;
  26.     Trap    : Boolean;
  27.     NextPtr : ObstaclePtr;
  28.     constructor Init(InitX, InitY, InitWidth : Integer; SetTrap : Boolean);
  29.     destructor Done; virtual;
  30.     function Collide(var B : Ball) : Boolean; virtual;
  31.     function IsTrap : Boolean; virtual;
  32.     function GetValue : Integer; virtual;
  33.   end;
  34.  
  35.   ObstacleList = object
  36.     Head : Obstacle;
  37.     Tail : ObstaclePtr;
  38.     constructor Init;
  39.     destructor Done; virtual;
  40.     procedure Append(NewObstacle : ObstaclePtr);
  41.     procedure Show;
  42.     procedure Hide;
  43.     function CheckCollisions(var B : Ball; var Score : Counter) : Boolean;
  44.   end;
  45.  
  46.   Paddle = object(Obstacle)
  47.     Color : Integer;
  48.     constructor Init(InitX, InitY, InitColor : Integer);
  49.     destructor Done; virtual;
  50.     procedure Show; virtual;
  51.     procedure Hide; virtual;
  52.     procedure MoveTo(NewX, NewY : Integer); virtual;
  53.     function Collide(var B : Ball) : Boolean; virtual;
  54.   end;
  55.  
  56.   { There are no instances of the object Boundary.  It's here to provide
  57.     a common basis for the next four objects. }
  58.   Boundary = object(Obstacle)
  59.     constructor Init(InitX, InitY, InitWidth : Integer; SetTrap : Boolean);
  60.   end;
  61.  
  62.   LeftBound = object(Boundary)
  63.     constructor Init(InitX, InitY, InitWidth : Integer; SetTrap : Boolean);
  64.     function Collide(var B : Ball) : Boolean; virtual;
  65.   end;
  66.  
  67.   UpperBound = object(Boundary)
  68.     constructor Init(InitX, InitY, InitWidth : Integer; SetTrap : Boolean);
  69.     function Collide(var B : Ball) : Boolean; virtual;
  70.   end;
  71.  
  72.   RightBound = object(Boundary)
  73.     constructor Init(InitX, InitY, InitWidth : Integer; SetTrap : Boolean);
  74.     function Collide(var B : Ball) : Boolean; virtual;
  75.   end;
  76.  
  77.   LowerBound = object(Boundary)
  78.     constructor Init(InitX, InitY, InitWidth : Integer; SetTrap : Boolean);
  79.     function Collide(var B : Ball) : Boolean; virtual;
  80.   end;
  81.  
  82. implementation
  83.  
  84. constructor Obstacle.Init(InitX, InitY, InitWidth : Integer;
  85.                           SetTrap : Boolean);
  86. begin
  87.   Location.Init(InitX, InitY);
  88.   Width := InitWidth;
  89.   Trap := SetTrap;
  90.   NextPtr := nil;
  91. end;
  92.  
  93. destructor Obstacle.Done;
  94. begin
  95. end;
  96.  
  97. function Obstacle.Collide(var B : Ball) : Boolean;
  98. begin
  99.   Collide := True;
  100. end;
  101.  
  102. function Obstacle.IsTrap : Boolean;
  103. begin
  104.   IsTrap := Trap;
  105. end;
  106.  
  107. function Obstacle.GetValue : Integer;
  108. begin
  109.   GetValue := 0;
  110. end;
  111.  
  112. constructor ObstacleList.Init;
  113. begin
  114.   Head.Init(0, 0, 0, False);
  115.   Tail := @Head;
  116. end;
  117.  
  118. destructor ObstacleList.Done;
  119. var
  120.   Temp1, Temp2 : ObstaclePtr;
  121. begin
  122.   Temp1 := Head.NextPtr;
  123.   while Temp1 <> nil do
  124.   begin
  125.     Temp2 := Temp1;
  126.     Temp1 := Temp1^.NextPtr;
  127.     Temp2^.Done;
  128.   end;
  129. end;
  130.  
  131. procedure ObstacleList.Append(NewObstacle : ObstaclePtr);
  132. begin
  133.   Tail^.NextPtr := NewObstacle;
  134.   Tail := NewObstacle;
  135. end;
  136.  
  137. procedure ObstacleList.Show;
  138. var
  139.   Current : ObstaclePtr;
  140. begin
  141.   Current := Head.NextPtr;
  142.   while Current <> nil do
  143.   begin
  144.     Current^.Show;
  145.     Current := Current^.NextPtr;
  146.   end;
  147. end;
  148.  
  149. procedure ObstacleList.Hide;
  150. var
  151.   Current : ObstaclePtr;
  152. begin
  153.   Current := Head.NextPtr;
  154.   while Current <> nil do
  155.   begin
  156.     Current^.Hide;
  157.     Current := Current^.NextPtr;
  158.   end;
  159. end;
  160.  
  161.  
  162. { This function is a little more complex than I like.  It checks
  163. whether a collision occurs, and updates the score if one does. }
  164.  
  165. function ObstacleList.CheckCollisions(var B : Ball;
  166.                                       var Score : Counter) : Boolean;
  167. var
  168.   Current : ObstaclePtr;
  169. begin
  170.   CheckCollisions := False;
  171.   Current := Head.NextPtr;
  172.   while Current <> nil do
  173.   begin
  174.     if Current^.Collide(B) then
  175.     begin
  176.       Score.Add(Current^.GetValue);
  177.       if Current^.IsTrap then
  178.         CheckCollisions := True;
  179.     end;
  180.     Current := Current^.NextPtr;
  181.   end;
  182. end;
  183.  
  184. constructor Paddle.Init(InitX, InitY, InitColor : Integer);
  185. begin
  186.   Obstacle.Init(InitX, InitY, 5, False);
  187.   Color := InitColor;
  188. end;
  189.  
  190. destructor Paddle.Done;
  191. begin
  192.   Obstacle.Done;
  193. end;
  194.  
  195. procedure Paddle.Show;
  196. var
  197.   Str : String[10];
  198. begin
  199.   FillChar(Str[1], Width, Chr(223));
  200.   Str[0] := Chr(Width);
  201.   Location.Show;
  202.   TextColor(Color);
  203.   GoToXY(X, Y);
  204.   Write(Str);
  205. end;
  206.  
  207. procedure Paddle.Hide;
  208. begin
  209.   Location.Hide;
  210.   GoToXY(X, Y);
  211.   Write('' : Width);
  212. end;
  213.  
  214. { The motion of Paddle is restricted to the 80-character screen }
  215.  
  216. procedure Paddle.MoveTo(NewX, NewY : Integer);
  217. begin
  218.   Hide;
  219.   if NewX < 1 then
  220.     X := 1
  221.   else if NewX > 81 - Width then
  222.     X := 81 - Width
  223.   else
  224.     X := NewX;
  225.   Y := NewY;
  226.   Show;
  227. end;
  228.  
  229. { If the ball hits the paddle we have to change the ball's direction.
  230.   Also, to keep the overall logic simpler, if the paddle is at the
  231.   edge of the screen and the ball would miss the paddle and go off the
  232.   edge, we call it a hit.  If we don't do this here, we get into some
  233.   complications with bouncing off the sides of the screen }
  234.  
  235. function Paddle.Collide(var B : Ball) : Boolean;
  236. var
  237.   NewX, NewY : Integer;
  238. begin
  239.   NewX := B.NextX;
  240.   NewY := B.NextY;
  241.   Collide := False;
  242.   if (NewY = Y) then
  243.     if ((NewX >= X) and (NewX < X + Width)) or
  244.       ((NewX < 1) and (X = 1)) or
  245.       ((NewX > 80) and (X + Width = 81)) then
  246.     begin
  247.       B.ReverseY;
  248. {$IFDEF Test}  { If the paddle is following the ball, we have to put
  249.                  in some random behavior so it doesn't get boring. }
  250.       B.ChangeXVel(Integer(Random(2))*2-1);
  251. {$ELSE}
  252.       B.ChangeXVel(B.GetX - X - 2);
  253. {$ENDIF}
  254.       Collide := True;
  255.     end;
  256. end;
  257.  
  258. constructor Boundary.Init(InitX, InitY, InitWidth : Integer;
  259.                           SetTrap : Boolean);
  260. begin
  261.   Obstacle.Init(InitX, InitY, InitWidth, SetTrap);
  262. end;
  263.  
  264. constructor LeftBound.Init(InitX, InitY, InitWidth : Integer;
  265.                            SetTrap : Boolean);
  266. begin
  267.   Boundary.Init(InitX, InitY, InitWidth, SetTrap);
  268. end;
  269.  
  270. function LeftBound.Collide(var B : Ball) : Boolean;
  271. begin
  272.   Collide := False;
  273.   if (B.NextX <= X) and (B.NextY >= Y) and (B.NextY <= Y + Width) then
  274.   begin
  275.     B.ReverseX;
  276.     Collide := True;
  277.   end;
  278. end;
  279.  
  280. constructor UpperBound.Init(InitX, InitY, InitWidth : Integer;
  281.                             SetTrap : Boolean);
  282. begin
  283.   Boundary.Init(InitX, InitY, InitWidth, SetTrap);
  284. end;
  285.  
  286. function UpperBound.Collide(var B : Ball) : Boolean;
  287. begin
  288.   Collide := False;
  289.   if (B.NextY <= Y) and (B.NextX >= X) and (B.NextX <= X + Width) then
  290.   begin
  291.     B.ReverseY;
  292.     Collide := True;
  293.   end;
  294. end;
  295.  
  296. constructor RightBound.Init(InitX, InitY, InitWidth : Integer;
  297.                             SetTrap : Boolean);
  298. begin
  299.   Boundary.Init(InitX, InitY, InitWidth, SetTrap);
  300. end;
  301.  
  302. function RightBound.Collide(var B : Ball) : Boolean;
  303. begin
  304.   Collide := False;
  305.   if (B.NextX >= X) and (B.NextY >= Y) and (B.NextY <= Y + Width) then
  306.   begin
  307.     B.ReverseX;
  308.     Collide := True;
  309.   end;
  310. end;
  311.  
  312. constructor LowerBound.Init(InitX, InitY, InitWidth : Integer;
  313.                             SetTrap : Boolean);
  314. begin
  315.   Boundary.Init(InitX, InitY, InitWidth, SetTrap);
  316. end;
  317.  
  318. function LowerBound.Collide(var B : Ball) : Boolean;
  319. begin
  320.   Collide := False;
  321.   if (B.NextY >= Y) and (B.NextX >= X) and (B.NextX <= X + Width) then
  322.   begin
  323.     B.ReverseY;
  324.     Collide := True;
  325.   end;
  326. end;
  327.  
  328. end.
  329.